package com.sinodata.bsm.cicp.collector.aix;

import java.io.BufferedReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.log4j.Logger;

import com.sinodata.bsm.cicp.collector.Collector;
import com.sinodata.bsm.cicp.exception.CollectorException;
import com.sinodata.bsm.cicp.util.CollectorUtil;
import com.sinodata.bsm.common.vo.ResPropertyValue;
import com.sinodata.bsm.common.vo.ResPropertyValue.PropValue;

/**
 * 
 * <p>
 * Description: comp% 算法 和 uncomp 算法 的采集器
 * </p>
 *
 * @author JonnyMo
 * @version 3.1

 * <p>
 * History: 新增
 *
 * Date                     Author         Version     Description
 * ---------------------------------------------------------------------------------
 * Jul 13, 2011 5:38:26 PM          Administrator        3.1         To create
 * </p>
 *
 * @since 
 * @see
 */
public class CompCollector extends Collector {
    private static final Logger logger = Logger.getLogger(CompCollector.class);

    @Override
    public List<ResPropertyValue> collect(String ip) throws CollectorException {
        List<ResPropertyValue> resProValList = null;
        BufferedReader uncompReader = null;
        BufferedReader compReader = null;
        try {
            compReader = CollectorUtil.getReader("vmstat -v", ip);
            uncompReader = CollectorUtil.getReader("svmon -G", ip);
            String[] uncomp = this.getMetaDataUncomp(uncompReader);
            String[] comp = this.getMetaDataComp(compReader);
            this.calcuData(uncomp, comp);
        } catch (IOException e) {
            logger.error("Failed to collector HA ", e);
            throw new CollectorException("Failed to collector HA ", e);
        } finally {
            if (compReader != null) {
                try {
                    compReader.close();
                } catch (IOException e) {
                    logger.error("Failed to close IO resource ", e);
                    throw new CollectorException("Failed to close IO Resource ", e);
                }
            }
            if (uncompReader != null) {
                try {
                    uncompReader.close();
                } catch (IOException e) {
                    logger.error("Failed to close IO resource ", e);
                    throw new CollectorException("Failed to close IO Resource ", e);
                }
            }
        }
        return resProValList;
    }

    /**
     * 使用给定的算法 来计算 提供的参数 
     * 
     * noncomp%算法: file pages/memory pages * 100 %
     * comp%算法: {work + pers +  clnt -filepages}/memorypages * 100 % 
     * 同时使用到svmon -G输出和vmstat -v的输出:
     * {in use行 work列的数值+[(inuse行pers列(非clnt,不同于永久存储)的数值+inuse行clnt列的数值)-(vmstat -v中file pages的值)]}/(vmstat -v中memory pages值) * 100%
     * @param noncomp, noncomp%算法 中需要的参数：0：memory pages  1：file pages（前面的数字是数组的角标）
     * @param comp  comp%算法中需要的部分参数 0:work       1:pers       2:clnt
     * @return
     * @throws IOException
     */
    private List<ResPropertyValue> calcuData(String[] noncomp, String[] comp) throws IOException {
        List<ResPropertyValue> resProValList = new ArrayList<ResPropertyValue>();
        ResPropertyValue propertyValueX = new ResPropertyValue();
        String[] propMetas = getPropMeta();
        PropValue[] propValues = new ResPropertyValue.PropValue[propMetas.length];
        //计算comp %算法 的值 file pages/memory pages*100%
        String noncompValue = ((Integer.parseInt(noncomp[1]) / Integer.parseInt(noncomp[0])) * 100) + "%";
        propValues[0] = ResPropertyValue.createPropValue(noncompValue, propMetas[0]);
        //计算uncomp %算法的值
        String compValue = (((Integer.parseInt(comp[0]) + Integer.parseInt(comp[1]) //
                        + Integer.parseInt(comp[2]) - Integer.parseInt(noncomp[1])) //
        / Integer.parseInt(noncomp[0])) * 100) + "%";
        propValues[1] = ResPropertyValue.createPropValue(compValue, propMetas[1]);
        propertyValueX.setValues(propValues);
        resProValList.add(propertyValueX);
        return resProValList;
    }

    /**
     * 获取 uncomp 算法 所需的参数
     * @param reader
     * @return 参数值
     * @throws IOException
     */
    private String[] getMetaDataUncomp(BufferedReader reader) throws IOException {
        String[] targetData = new String[2];
        String tmp = null;
        //匹配    524288 memory pages
        Pattern memPagesPatn = Pattern.compile("\\s*(\\d+)\\s*memory\\s*pages\\s*");
        //匹配    50220 file pages
        Pattern filePagesPatn = Pattern.compile("\\s*(\\d+)\\s*file\\s*pages\\s*");
        Matcher memMach = null;
        Matcher fileMach = null;
        while ((tmp = reader.readLine()) != null) {
            memMach = memPagesPatn.matcher(tmp);
            fileMach = filePagesPatn.matcher(tmp);
            if (memMach.matches()) {
                targetData[0] = memMach.group(1);
                System.out.println("memory pages: " + targetData[0]);
            } else if (fileMach.matches()) {
                targetData[1] = fileMach.group(1);
                System.out.println("file pages: " + targetData[1]);
            }
        }
        return targetData;
    }

    /**
     * 解析获得 comp算法所需的其他参数
     * @param reader
     * @return 参数值
     * @throws IOException
     */
    private String[] getMetaDataComp(BufferedReader reader) throws IOException {
        String tmp = null;
        //感兴趣的 参数出现在同一行内
        Pattern inUsePatn = Pattern.compile("\\s*in\\s*use\\s*(\\d+)\\s*(\\d+)*(\\d+)\\s*");
        Matcher inUseMach = null;
        String[] targetData = new String[3];
        while ((tmp = reader.readLine()) != null) {
            inUseMach = inUsePatn.matcher(tmp);
            if (inUseMach.matches()) {
                targetData[0] = inUseMach.group(1);
                targetData[1] = inUseMach.group(2);
                targetData[2] = inUseMach.group(3);
                break;
            }
        }
        return targetData;
    }

    @Override
    public String[] getParamMeta() {
        return null;
    }

    @Override
    public String[] getPropMeta() {
        return new String[] { "noncomp%", "comp%" };
    }

}
